package com.cardone.common.function;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;

import lombok.extern.slf4j.Slf4j;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveInputStream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang.StringUtils;

import com.cardone.common.util.CipherUtils;
import com.cardone.context.DictionaryException;
import com.cardone.context.function.Execution2Function;

/**
 * ContextHolder.getBean(UnZipFileFunction.class).execution(filename, password);
 *
 * @author yaohaitao
 *
 */
@Slf4j
public class UnZipFileFunction implements Execution2Function<String, String, String> {
	@Override
	public String execution(final String zipFilename, final String password) {
		final String fileFullPath = FilenameUtils.getFullPath(zipFilename);

		final String fileBaseName = FilenameUtils.getBaseName(zipFilename);

		final String fileExtension = FilenameUtils.getExtension(zipFilename);

		String filename = null;

		final String tempFilename = StringUtils.join(new String[] { fileFullPath, fileBaseName, "_temp.", fileExtension });

		final int bufferLen = 1024 * 1024;

		final File zipFile = new File(tempFilename);

		final File outDir = new File(fileFullPath);

		ZipArchiveInputStream is = null;

		try {
			CipherUtils.decrypt(zipFilename, tempFilename, password);
		} catch (final Exception e) {
			throw new DictionaryException("解密失败", e);
		}

		try {
			is = new ZipArchiveInputStream(new BufferedInputStream(new FileInputStream(zipFile), bufferLen));

			ZipArchiveEntry entry = null;

			while ((entry = is.getNextZipEntry()) != null) {
				if (entry.isDirectory()) {
					final File directory = new File(outDir, entry.getName());
					directory.mkdirs();

					break;
				}

				OutputStream os = null;

				try {
					os = new BufferedOutputStream(new FileOutputStream(new File(outDir, entry.getName())), bufferLen);

					IOUtils.copy(is, os);
				} finally {
					IOUtils.closeQuietly(os);
				}

				filename = StringUtils.join(new String[] { fileFullPath, entry.getName() });
			}
		} catch (final IOException e) {
			UnZipFileFunction.log.error(e.getMessage(), e);
		} finally {
			IOUtils.closeQuietly(is);

			FileUtils.deleteQuietly(new File(tempFilename));
		}

		return filename;
	}
}
